package com.qsxc.utils;

import com.qsxc.business.bean.ResultCode;
import com.qsxc.system.exception.CustomException;
import com.qsxc.system.log.LogUtil;
import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;

/**
 * DateTime 工具类
 */
@Slf4j
public class DateTimeUtil {

    public static final Long TIME_SIZE_DAY = 1000 * 60 * 60 * 24L;
    public static final Long TIME_SIZE_HOUR = 1000 * 60 * 60L;
    public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME);
    public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATE);
    public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_TIME);
    public static final String DATE_FORMAT_1 = "yyyy-MM-dd HH:mm:ss";

    public static final String FULL_TIME = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_DATE = "yyyy-MM-dd";

    private static final long ONE_MINUTE = 60;
    private static final long ONE_HOUR = 3600;
    private static final long ONE_DAY = 86400;
    private static final long ONE_MONTH = 2592000;
    private static final long ONE_YEAR = 31104000;

    public static LocalDateTime date2LocalDateTime(Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static Date localDateTime2Date(LocalDate localDate) {
        if (null == localDate) {
            return null;
        }
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    public static LocalDate date2LocalDate(Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static Date localDate2Date(LocalDate localDate) {
        if (null == localDate) {
            return null;
        }
        ZonedDateTime zonedDate = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDate.toInstant());
    }

    /**
     * 日期时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatDateTime(TemporalAccessor temporal) {
        return DATETIME_FORMAT.format(temporal);
    }

    public static String formatDateTime(Date date) {
        if (date == null) {
            return null;
        }
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return formatDateTime(localDateTime);
    }

    /**
     * 日期时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatDate(TemporalAccessor temporal) {
        return DATE_FORMAT.format(temporal);
    }

    public static String formatDate(Date date) {
        if (date == null) {
            return null;
        }
        return formatDate(date2LocalDate(date));
    }

    /**
     * 时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatTime(TemporalAccessor temporal) {
        return TIME_FORMAT.format(temporal);
    }

    public static String formatTime(Date date) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        return formatTime(localDateTime);
    }

    /**
     * 日期格式化
     *
     * @param temporal 时间
     * @param pattern  表达式
     * @return 格式化后的时间
     */
    public static String format(TemporalAccessor temporal, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(temporal);
    }

    public static String format(Date date, String pattern) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        return DateTimeFormatter.ofPattern(pattern).format(localDateTime);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 表达式
     * @return 时间
     */
    public static TemporalAccessor parse(String dateStr, String pattern) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
        return format.parse(dateStr);
    }

    public static Date parseToDate(String dateStr, String pattern) {
        TemporalAccessor temporalAccessor = parse(dateStr, pattern);
        return Date.from(toInstant(LocalDateTime.from(temporalAccessor)));
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr   时间字符串
     * @param formatter DateTimeFormatter
     * @return 时间
     */
    public static TemporalAccessor parse(String dateStr, DateTimeFormatter formatter) {
        return formatter.parse(dateStr);
    }

    public static Date parseToDate(String dateStr, DateTimeFormatter formatter) {
        TemporalAccessor temporalAccessor = parse(dateStr, formatter);
        return Date.from(toInstant(LocalDateTime.from(temporalAccessor)));
    }

    /**
     * 时间转 Instant
     *
     * @param dateTime 时间
     * @return Instant
     */
    public static Instant toInstant(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    /**
     * Instant 转 时间
     *
     * @param instant Instant
     * @return Instant
     */
    public static LocalDateTime toDateTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    /**
     * @param
     * @param
     * @return
     * @author zhu 获得当前日期
     */
    public static String getCurrentTimeDef() {
        DateFormat format1 = new SimpleDateFormat("yyyyMMddHHmmss");
        String dataString = format1.format(new Date()).toString();
        return dataString;
    }

    /**
     * 如果是月份加减cal.add(2, i); 如果是星期加减cal.add(3, i); 如果是每日加减cal.add(5, i);
     * 如果是小时加减cal.add(10, i); 如果是分钟加减cal.add(12, i); 如果是秒的加减cal.add(13, i);
     *
     * @return
     */

    public static Date addDateOrMinusYear(Date date, int ti, int i) {
        try {
            Date rtn = null;
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(ti, i);
            rtn = cal.getTime();
            return rtn;
        } catch (Exception e) {
            throw new CustomException("日期运算异常", ResultCode.CUSTOM_FAIL.getCode());
        }
    }

    /**
     * 字符串类型开始时间和结束时间比较 yyyy-MM-dd HH:mm:ss
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static boolean compareTime(String startTime, String endTime) {
        Date startDate = strToDateTime(startTime);
        Date endDate = strToDateTime(endTime);
        if (endDate.after(startDate)) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 字符串转时间
     *
     * @param str yyyy-MM-dd HH:mm:ss
     * @return
     * @throws Exception
     */
    public static Date strToDateTime(String str) {
        if (str == null || "".equals(str)) {
            return null;
        }
        String format = "yyyy-MM-dd HH:mm:ss";
        if (str.length() == 14) {
            format = "yyyyMMddHHmmss";
        } else if (str.length() == 12) {
            format = "yyyyMMddHHmm";
        } else if (str.length() == "yyyy-MM-dd".length()) {
            format = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = sdf.parse(str);
        } catch (ParseException e) {
            LogUtil.error(e.getMessage(), e);
        }
        return date;
    }

    public static Date strToDateTime(String str, String format) {
        if (str == null || "".equals(str)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = sdf.parse(str);
        } catch (ParseException e) {
            LogUtil.error(e.getMessage(), e);
        }
        return date;
    }

    /**
     * 时间转字符串（年月日 时分秒）
     *
     * @param date
     * @return
     * @throws Exception
     */
    public static String dateToString(Date date) {
        String format = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String str = new String();
        if (null == date) {
            return "";
        } else {
            str = sdf.format(date);
            return str;
        }
    }

    public static String dateToString(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String str = new String();
        if (null == date) {
            return "";
        } else {
            str = sdf.format(date);
            return str;
        }
    }

    /**
     * 统一的时间构造方法
     *
     * @param date
     * @param simpleDateFormat
     * @return
     */
    public static String toSimpleDateFormat(Date date, String simpleDateFormat) {
        SimpleDateFormat format = new SimpleDateFormat(simpleDateFormat);
        if (date == null) {
            return null;
        } else {
            try {
                return format.format(date);
            } catch (Exception ex) {
                ex.printStackTrace();
                return null;
            }
        }
    }

    /**
     * 将字符串时间转成年月日的字符串时间
     *
     * @param time
     * @return
     * @throws ParseException
     */
    public static String getFormatYYmmdd(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String currentDay = null;
        try {
            currentDay = format.format(format.parse(time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return currentDay;
    }

    /**
     * 将字符串时间转成时分的字符串时间
     *
     * @param time
     * @return
     */
    public static String getFormatHHmm(String time) {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        time = time.substring(11);
        String currentDay = null;
        try {
            currentDay = format.format(format.parse(time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return currentDay;
    }

    /**
     * 将字符串时间转成年月日的字符串时间
     *
     * @param time
     * @return
     * @throws ParseException
     */
    public static String getFormatYYmmddHHmmss(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentDay = null;
        try {
            currentDay = format.format(format.parse(time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return currentDay;
    }

    public static Date dateAddTime(Date date, Date time) {
        String full = dateToString(date, "yyyy-MM-dd ") + dateToString(time, "HH:mm:ss");
        return strToDateTime(full);
    }

    /**
     * JAVA计算两个日期相差多少天(by date)
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int daysBetween(Date date1, Date date2) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 距离今天多久
     *
     * @param date
     * @return
     */
    public static String fromToday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        long time = date.getTime() / 1000;
        long now = new Date().getTime() / 1000;
        long ago = now - time;
        if (ago <= ONE_HOUR) {
            return ago / ONE_MINUTE + "分钟前";
        } else if (ago <= ONE_DAY) {
            if (ago % ONE_HOUR / ONE_MINUTE == 0) {
                return ago / ONE_HOUR + "小时前";
            } else {
                return ago / ONE_HOUR + "小时" + (ago % ONE_HOUR / ONE_MINUTE) + "分钟前";
            }
        } else if (ago <= ONE_DAY * 2) {
            if (calendar.get(Calendar.MINUTE) == 0) {
                return "昨天" + calendar.get(Calendar.HOUR_OF_DAY) + "点";
            } else {
                return "昨天" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE) + "分";
            }
        } else if (ago <= ONE_DAY * 3) {
            if (calendar.get(Calendar.MINUTE) == 0) {
                return "前天" + calendar.get(Calendar.HOUR_OF_DAY) + "点";
            } else {
                return "前天" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE) + "分";
            }
        } else if (ago <= ONE_MONTH) {
            long day = ago / ONE_DAY;
            if (calendar.get(Calendar.MINUTE) == 0) {
                return day + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点";
            } else {
                return day + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE) + "分";
            }
        } else if (ago <= ONE_YEAR) {
            long month = ago / ONE_MONTH;
            long day = ago % ONE_MONTH / ONE_DAY;
            if (calendar.get(Calendar.MINUTE) == 0) {
                return month + "个月" + day + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点";
            } else {
                return month + "个月" + day + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE) + "分";
            }
        } else {
            long year = ago / ONE_YEAR;
            int month = calendar.get(Calendar.MONTH) + 1;// JANUARY which is 0 so month+1
            return year + "年前" + month + "月" + calendar.get(Calendar.DATE) + "日";
        }
    }

}
